﻿<%
    import plexpy
    from plexpy import common, helpers
%>

<!doctype html>

<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Tautulli - ${title} | ${server_name}</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="description" content="">
    <meta name="author" content="">
    <meta name="referrer" content="no-referrer">
    <link href="${http_root}css/bootstrap3/bootstrap.min.css" rel="stylesheet">
    <link href="${http_root}css/bootstrap-wizard.css" rel="stylesheet">
    <link href="${http_root}css/tautulli.css${cache_param}" rel="stylesheet">
    <link href="${http_root}css/selectize.bootstrap3.css" rel="stylesheet">
    <link href="${http_root}css/opensans.min.css" rel="stylesheet">
    <link href="${http_root}css/font-awesome.all.min.css" rel="stylesheet">
    <link href="${http_root}css/font-awesome.v4-shims.min.css" rel="stylesheet">

    <!-- Favicons -->
    <link rel="icon" type="image/png" sizes="32x32" href="${http_root}images/favicon/favicon-32x32.png?v=2.6.0">
    <link rel="icon" type="image/png" sizes="16x16" href="${http_root}images/favicon/favicon-16x16.png?v=2.6.0">
    <link rel="shortcut icon" href="${http_root}images/favicon/favicon.ico?v=2.6.0">

    <!-- ICONS -->
    <!-- Android -->
    <link rel="manifest" href="${http_root}images/favicon/manifest.json?v=2.9.0" crossorigin="use-credentials">
    <meta name="theme-color" content="#282a2d">
    <!-- Apple -->
    <link rel="apple-touch-icon" sizes="180x180" href="${http_root}images/favicon/apple-touch-icon.png?v=2.6.0">
    <link rel="mask-icon" href="${http_root}images/favicon/safari-pinned-tab.svg?v=2.6.0" color="#282a2d">
    <meta name="apple-mobile-web-app-title" content="Tautulli">
    <!-- Microsoft -->
    <meta name="application-name" content="Tautulli">
    <meta name="msapplication-config" content="${http_root}images/favicon/browserconfig.xml?v=2.6.0">
</head>

<body>
<div class="container-fluid">
    % if plexpy.CONFIG.CHECK_DOCKER_MOUNT and plexpy.DOCKER and not plexpy.DOCKER_MOUNT:
    <div class="row">
        <div class="col-md-12">
            <div class="alert alert-danger docker-mount" role="alert" style="width: 700px; z-index: 9999">
                The <span class="inline-pre">/config</span> volume mount was not configured properly for the Docker container.
                All data may be cleared when the container is recreated or updated.
            </div>
        </div>
    </div>
    % endif
    <div class="row">
        <div class="wizard" id="setup-wizard" data-title="Tautulli Setup Wizard">
            <form>
                <div class="wizard-card" data-cardname="card1">
                    <div style="float: right;">
                        <img src="${http_root}images/logo-tautulli-45.png" height="45" alt="Tautulli">
                    </div>
                    <h3 style="line-height: 50px;">Welcome!</h3>
                    <div class="wizard-input-section">
                        <p class="welcome-message">
                            Thanks for taking the time to try out Tautulli. Hope you find it useful.
                        </p>
                        <p class="welcome-message">
                            Tautulli requires a permanent internet connection to ensure a reliable experience.
                        </p>
                        <p class="welcome-message">
                            This wizard will help you get set up, to continue press Next.
                        </p>
                    </div>
                </div>

                <div class="wizard-card" data-cardname="card2">
                    <h3>Authentication</h3>
                    <div class="wizard-input-section">
                        <p class="help-block">
                            Please setup an admin username and password for Tautulli.
                        </p>
                    </div>
                    <div class="wizard-input-section">
                        <label for="http_username">HTTP Username</label>
                        <div class="row">
                            <div class="col-xs-8">
                                <input type="text" class="form-control auth-settings" id="http_username" name="http_username" value="" size="30">
                            </div>
                        </div>
                    </div>
                    <div class="wizard-input-section">
                        <label for="http_password">HTTP Password</label>
                        <div class="row">
                            <div class="col-xs-8">
                                <div class="input-group">
                                    <input type="password" class="form-control auth-settings" id="http_password" name="http_password" value="" size="30" autocomplete="new-password">
                                    <span class="input-group-btn">
                                        <button class="btn btn-form reveal-token" type="button"><i class="fa fa-eye-slash"></i></button>
                                    </span>
                                </div>
                            </div>
                        </div>
                    </div>
                    <input type="hidden" class="form-control" name="http_plex_admin" id="http_plex_admin" value="1">
                    <input type="hidden" id="authentication_valid" data-validate="validateAuthentication" value="">
                    <span style="display: none;" id="authentication-status"></span>
                </div>

                <div class="wizard-card" data-cardname="card3">
                    <h3>Plex Account</h3>
                    <div class="wizard-input-section">
                        <p class="help-block">
                            Tautulli requires a Plex.tv account. Click the button below to sign in on Plex.tv. You may need to allow popups in your browser.
                        </p>
                    </div>
                    <input type="hidden" id="pms_token_validated" value="0" data-validate="validatePMStoken">
                    <input type="hidden" name="pms_client_id" id="pms_client_id" value="">
                    <button id="sign-in-plex" class="btn btn-form" type="button">Sign In with Plex</button>
                    <span style="margin-left: 10px; display: none;" id="pms-token-status"></span>
                </div>

                <div class="wizard-card" data-cardname="card4">
                    <h3>Plex Media Server</h3>
                    <div class="wizard-input-section">
                        <p class="help-block">
                            Select your Plex Media Server from the dropdown menu or enter an IP address or hostname.
                        </p>
                    </div>
                    <div class="wizard-input-section">
                        <label for="pms_ip_selectize">Plex IP Address or Hostname</label>
                        <div class="row">
                            <div class="col-xs-12">
                                <select class="form-control pms-settings selectize-pms-ip" id="pms_ip_selectize">
                                    % if config['pms_identifier']:
                                    <option value="${config['pms_ip']}:${config['pms_port']}"
                                            data-identifier="${config['pms_identifier']}"
                                            data-ip="${config['pms_ip']}"
                                            data-port="${config['pms_port']}"
                                            data-ssl="${config['pms_ssl']}"
                                            data-is_cloud="${config['pms_is_cloud']}"
                                            data-label="${config['pms_name'] or 'Local'}"
                                            selected>${config['pms_ip']}</option>
                                    % endif
                                </select>
                            </div>
                        </div>
                    </div>
                    <div class="wizard-input-section">
                        <label for="pms_port">Plex Port</label>
                        <div class="row">
                            <div class="col-xs-3">
                                <input type="text" class="form-control pms-settings" name="pms_port" id="pms_port" placeholder="32400" value="${config['pms_port']}" required>
                            </div>
                            <div class="col-xs-9">
                                <div class="checkbox">
                                    <label>
                                        <input type="checkbox" id="pms_ssl_checkbox" class="checkbox-toggle pms-settings" data-id="pms_ssl" value="1" ${helpers.checked(config['pms_ssl'])}> Use Secure Connection
                                        <input type="hidden" id="pms_ssl" name="pms_ssl" value="${config['pms_ssl']}">
                                    </label>
                                </div>
                            </div>
                        </div>
                    </div>
                    <input type="hidden" id="pms_valid" data-validate="validatePMSip" value="">
                    <input type="hidden" id="pms_ip" name="pms_ip" value="${config['pms_ip']}">
                    <input type="hidden" id="pms_is_cloud" name="pms_is_cloud" value="${config['pms_is_cloud']}">
                    <input type="hidden" id="pms_identifier" name="pms_identifier" value="${config['pms_identifier']}">
                    <a class="btn btn-dark" id="verify-plex-server" href="#" role="button">Verify</a>
                    <span style="margin-left: 10px; display: none;" id="pms-verify-status"></span>
                </div>

                <div class="wizard-card" data-cardname="card5">
                    <h3>Activity Logging</h3>
                    <div class="wizard-input-section">
                        <p class="help-block">
                            Tautulli will keep a history of all streaming activity on your Plex server.
                        </p>
                    </div>
                    <div class="wizard-input-section">
                        <label for="logging_ignore_interval">Ignore Interval</label>
                        <div class="row">
                            <div class="col-xs-4">
                                <input type="text" class="form-control pms-monitoring" id="logging_ignore_interval" name="logging_ignore_interval" placeholder="120" value="${config['logging_ignore_interval']}" data-validate="validateIgnoreInterval" required>
                            </div>
                            <span style="margin-left: 10px; line-height: 35px; display: none;" id="ignore-int-status"></span>
                        </div>
                        <p class="help-block">The interval (in seconds) an item must be in a playing state before logging it. 0 to disable.</p>
                    </div>
                    <div class="wizard-input-section">
                        <p class="help-block">
                            Additional options to disable history logging for certain libraries or users can be found by editing them
                            on the <strong>Libraries</strong> or <strong>Users</strong> pages.
                        </p>
                    </div>
                </div>

                <div class="wizard-card" data-cardname="card6">
                    <h3>Notifications</h3>
                    <div class="wizard-input-section">
                        <p class="help-block">
                            Tautulli can send a wide variety of notifications to alert you of activity on your Plex server.
                        </p>
                        <p class="help-block">
                            To set up a notification agent, navigate to the <strong>Settings</strong> page
                            and to the <strong>Notification Agents</strong> tab after you have completed this setup wizard.
                        </p>
                    </div>
                </div>

                <div class="wizard-card" data-cardname="card7">
                    <h3>Database Import</h3>
                    <div class="wizard-input-section">
                        <p class="help-block">
                            If you have an existing Tautulli, PlexWatch, or Plexivity database, you can import the data into Tautulli.
                        </p>
                        <p class="help-block">
                            To import a database, navigate to the <strong>Settings</strong> page
                            and to the <strong>Import & Backups</strong> tab after you have completed this setup wizard.
                        </p>
                    </div>

                    <!-- Required fields but hidden -->
                    <div style="display: none;">
                        <input type="checkbox" name="first_run" id="first_run" value="1" checked>
                    </div>

                </div>

            </form>
            <div class="wizard-success">
                <h3>Setup Complete!</h3>
                <br/>
                <p>Setup is now complete. For more configuration options please visit the Settings menu on the home page.</p>
                <br/>
                <i class="fa fa-refresh fa-spin"></i>&nbspWaiting <span class="countdown">5</span> seconds to ensure authentication token is registered...

            </div>
        </div>
    </div>
</div>

<script src="${http_root}js/jquery-3.6.0.min.js"></script>
<script src="${http_root}js/bootstrap.min.js"></script>
<script src="${http_root}js/selectize.min.js"></script>
<script src="${http_root}js/platform.min.js"></script>
<script src="${http_root}js/script.js${cache_param}"></script>
<script src="${http_root}js/bootstrap-wizard.min.js"></script>
<script>
    function validateAuthentication(el) {
        var http_username = $("#http_username").val();
        var http_password = $("#http_password").val();
        var valid_authentication = el.val();
        var retValue = {};

        if (http_username === "" || http_password === "") {
            retValue.status = false;
            retValue.msg = "Please enter a username and password.";
            $("#authentication-status").html('<i class="fa fa-exclamation-circle"></i> Please enter a username and password.');
            $('#authentication-status').fadeIn('fast').delay(2000).fadeOut('fast');
        } else {
            retValue.status = true;
        }

        return retValue;
    }

    function validatePMSip(el) {
        var valid_pms_ip = el.val();
        var retValue = {};

        if (valid_pms_ip === "") {
            retValue.status = false;
            retValue.msg = "Please verify your server.";
            $("#pms-verify-status").html('<i class="fa fa-exclamation-circle"></i> Please verify your server.');
            $('#pms-verify-status').fadeIn('fast').delay(2000).fadeOut('fast');
        } else {
            retValue.status = true;
        }

        return retValue;
    }

    function validatePMStoken(el) {
        var valid_pms_token = el.val();
        var retValue = {};

        if (valid_pms_token !== "1") {
            retValue.status = false;
            retValue.msg = "Please authenticate.";
            $("#pms-token-status").html('<i class="fa fa-exclamation-circle"></i> Please authenticate.');
            $('#pms-token-status').fadeIn('fast').delay(2000).fadeOut('fast');
        } else {
            retValue.status = true;
        }

        return retValue;
    }

    function validateIgnoreInterval(el) {
        var valid_ignore_int = el.val();
        var retValue = {};

        if (!isPositiveInt(valid_ignore_int)) {
            retValue.status = false;
            retValue.msg = "Please enter a valid integer.";
            $("#ignore-int-status").html('<i class="fa fa-exclamation-circle"></i> Please enter a valid ignore interval.');
            $('#ignore-int-status').fadeIn('fast').delay(2000).fadeOut('fast');
        } else {
            retValue.status = true;
        }

        return retValue;
    }

    function isPositiveInt(n) {
        return $.isNumeric(n) && (Math.floor(n) == n) && (n >= 0)
    }

$(document).ready(function() {

    $.fn.wizard.logging = false;
    var options = {
        keyboard : false,
        contentHeight : 450,
        contentWidth : 700,
        backdrop: 'static',
        buttons: {submitText: 'Finish'},
        submitUrl: "configUpdate"
    };
    var wizard = $("#setup-wizard").wizard(options);
    wizard.show();

    // Change button classes
    wizard.find('.wizard-back').addClass('btn-dark');
    wizard.on('incrementCard', function(wizard) {
        wizard.find('.wizard-next.btn-success').removeClass('btn-success').addClass('btn-bright');
    });
    wizard.on('decrementCard', function(wizard) {
        wizard.find('.wizard-next').removeClass('btn-bright').text('Next');
    });

    wizard.on("submit", function(wizard) {
        // Probably should not success before we know, but hopefully validation is good enough.
        wizard.submitSuccess();
        $.ajax({
            type: "POST",
            url: wizard.args.submitUrl,
            data: wizard.serialize(),
            dataType: "json",
            complete: function (data) {
                $(".countdown").countdown(function () { location.reload(); }, 5, "");
            }
        })
    });

    $('.checkbox-toggle').click(function () {
        var configToggle = $(this).data('id');
        if ($(this).is(':checked')) {
            $('#'+configToggle).val(1);
        } else {
            $('#'+configToggle).val(0);
        }
    });

    var $select_pms = $('#pms_ip_selectize').selectize({
        createOnBlur: true,
        openOnFocus: true,
        maxItems: 1,
        closeAfterSelect: true,
        sortField: 'label',
        searchField: ['label', 'value'],
        inputClass: 'form-control selectize-input',
        render: {
            item: function (item, escape) {
                if (!item.label) {
                    $.extend(item,
                        $(this.revertSettings.$children)
                             .filter('[value="' + item.value + '"]').data()
                    );
                }
                var label = item.label || item.value;
                var caption = item.label ? item.ip : null;
                return '<div data-identifier="' + item.clientIdentifier +
                        '" data-ip="' + item.ip +
                        '" data-port="' + item.port +
                        '" data-ssl="' + item.httpsRequired +
                        '" data-is_cloud="' + item.is_cloud +
                        '" data-label="' + item.label + '">' +
                        '<span class="item-text">' + escape(label) + '</span>' +
                        (caption ? '<span class="item-value">' + escape(caption) + '</span>' : '') +
                        '</div>';
            },
            option: function (item, escape) {
                var label = item.label || item.value;
                var caption = item.label ? item.value : null;
                return '<div data-identifier="' + item.clientIdentifier +
                        '" data-ip="' + item.ip +
                        '" data-port="' + item.port +
                        '" data-ssl="' + item.httpsRequired +
                        '" data-is_cloud="' + item.is_cloud +
                        '" data-label="' + item.label + '">' +
                        escape(label) +
                        (caption ? '<span class="caption">' + escape(caption) + '</span>' : '') +
                        '</div>';
            }
        },
        create: function(input) {
            return {label: '', value: input};
        },
        onInitialize: function () {
            var s = this;
            this.revertSettings.$children.each(function () {
                $.extend(s.options[this.value], $(this).data());
            });
        },
        onChange: function (item) {
            var pms_ip_selected = this.getItem(item)[0];
            var identifier = $(pms_ip_selected).data('identifier');
            var ip = $(pms_ip_selected).data('ip');
            var port = $(pms_ip_selected).data('port');
            var ssl = $(pms_ip_selected).data('ssl');
            var is_cloud = $(pms_ip_selected).data('is_cloud');
            var value = $(pms_ip_selected).data('value');

            $("#pms_valid").val(identifier !== 'undefined' ? 'valid' : '');
            $("#pms-verify-status").html(identifier !== 'undefined' ? '<i class="fa fa-check"></i>&nbsp; Server found!' : '').fadeIn('fast');

            $("#pms_identifier").val(identifier !== 'undefined' ? identifier : '');
            $('#pms_ip').val(ip !== 'undefined' ? ip : value);
            $('#pms_port').val(port !== 'undefined' ? port : 32400);
            $('#pms_ssl_checkbox').prop('checked', (ssl !== 'undefined' && ssl === 1));
            $('#pms_ssl').val(ssl !== 'undefined' && ssl === 1 ? 1 : 0);
            $('#pms_is_cloud').val(is_cloud !== 'undefined' && is_cloud === true ? 1 : 0);

            if (is_cloud === true) {
                $('#pms_port').prop('readonly', true);
                $('#pms_ssl_checkbox').prop('disabled', true);
            } else {
                $('#pms_port').prop('readonly', false);
                $('#pms_ssl_checkbox').prop('disabled', false);
            }
        },
        onDropdownOpen: function() {
            this.clear();
        }
    });
    var select_pms = $select_pms[0].selectize;

    function getServerOptions() {
        $.ajax({
            url: 'discover',
            success: function (result) {
                if (result) {
                    var existing_ip = $('#pms_ip').val();
                    var existing_port = $('#pms_port').val();
                    result.forEach(function (item) {
                        if (item.ip === existing_ip && item.port === existing_port) {
                            select_pms.updateOption(item.value, item);
                        } else {
                            select_pms.addOption(item);
                        }
                    });
                }
            }
        })
    }
    var pms_verified = false;
    var authenticated = false;

    $("#verify-plex-server").click(function () {
        if (!(pms_verified)) {
            var pms_ip = $("#pms_ip").val().trim();
            var pms_port = $("#pms_port").val().trim();
            var pms_identifier = $("#pms_identifier").val();
            var pms_ssl = $("#pms_ssl").val();
            if ((pms_ip !== '') || (pms_port !== '')) {
                $("#pms-verify-status").html('<i class="fa fa-refresh fa-spin"></i>&nbsp; Verifying server...');
                $('#pms-verify-status').fadeIn('fast');
                $.ajax({
                    url: 'get_server_id',
                    data: {
                        hostname: pms_ip,
                        port: pms_port,
                        identifier: pms_identifier,
                        ssl: pms_ssl
                    },
                    cache: true,
                    async: true,
                    timeout: 5000,
                    error: function (jqXHR, textStatus, errorThrown) {
                        $("#pms-verify-status").html('<i class="fa fa-exclamation-circle"></i>&nbsp; Error verifying server: ' + textStatus);
                        $('#pms-verify-status').fadeIn('fast');
                    },
                    success: function(xhr, status) {
                        var result = xhr;
                        var identifier = result.identifier;
                        if (identifier) {
                            $("#pms_identifier").val(identifier);
                            $("#pms-verify-status").html('<i class="fa fa-check"></i>&nbsp; Server found!');
                            $('#pms-verify-status').fadeIn('fast');
                            pms_verified = true;
                            $("#pms_valid").val("valid");
                        } else {
                            $("#pms-verify-status").html('<i class="fa fa-exclamation-circle"></i>&nbsp; This is not a Plex Server!');
                            $('#pms-verify-status').fadeIn('fast');
                        }
                    }
                });
            } else {
                $("#pms-verify-status").html('<i class="fa fa-exclamation-circle"></i>&nbsp; Please enter both fields.');
                $('#pms-verify-status').fadeIn('fast');
            }
        }
    });

    $( ".pms-settings" ).change(function() {
        pms_verified = false;
        $("#pms_valid").val("");
        $("#pms-verify-status").html("");
    });

    function OAuthPreFunction() {
        $("#pms-token-status").html('<i class="fa fa-refresh fa-spin"></i>&nbsp; Waiting for authentication...').fadeIn('fast');
    }
    function OAuthSuccessCallback(authToken) {
        $.post('save_pms_token', { token: authToken, client_id: $('#pms_client_id').val() }, function () {
            $("#pms_token_validated").val(1);
            getServerOptions();
        });
        $("#pms-token-status").html('<i class="fa fa-check"></i>&nbsp; Authentication successful.').fadeIn('fast');
        authenticated = true;
    }
    function OAuthErrorCallback() {
        $("#pms-token-status").html('<i class="fa fa-exclamation-circle"></i>&nbsp; Error communicating with Plex.tv.').fadeIn('fast');
    }

    $('#sign-in-plex').click(function() {
        PlexOAuth(OAuthSuccessCallback, OAuthErrorCallback, OAuthPreFunction, $('#pms_client_id').val(uuidv4()).val());
    });
});
</script>

</body>
</html>
